Simple Texture Image Animation for Flaming Torches

To provide an animated effect for the flaming torch objects a simple behavior was used to modify the Transform3D within the objects TextureAttributes. Even slight movement of the texture image was found to give quite pleasing results.

The Light class defines the geometry and simple texture animation behavior for the light. Light is derived from the reusable ComplexObject class (defined in the com.tornadlabs.dselman.j3d.book package).

figure 5. The texture images used by the KeyNaviagateTest example application. Floor 128x128 (1), Ceiling 128 x 128 (2), Walls 32x32 transparent background (3), Lights 32x32 transparent background (4), Bookcases 32x32 (5), Water 32x32 (6).

From Light.java:

public class Light extends ComplexObject

{

private TextureAttributes m_TextureAttributes = null;

public Light( Component comp, Group g, int nFlags )

{

super( comp, g, nFlags );

}

protected Group createGeometryGroup( Appearance app, Vector3d position, Vector3d scale, String szTextureFile, String szSoundFile )

{

Group g = new Group();

draw all the faces of the object

app.setPolygonAttributes( new PolygonAttributes( PolygonAttributes.POLYGON_FILL, PolygonAttributes.CULL_NONE, 0, false ) );

the texture image for the light includes transparent areas for the background. By making the object fully transparent we can just draw an irregular shaped texture image

app.setTransparencyAttributes( new TransparencyAttributes( TransparencyAttributes.BLENDED, 1.0f ) );

assign a TextureAttributes object to the Appearance and keep a reference to it so we can modify it

m_TextureAttributes = new TextureAttributes( TextureAttributes.REPLACE, new Transform3D(), new Color4f(0,0,0,1), TextureAttributes.FASTEST );

app.setTextureAttributes( m_TextureAttributes );

apply the texture image

if( (m_nFlags & ComplexObject.TEXTURE) == ComplexObject.TEXTURE )

setTexture( app, szTextureFile );

create the geometry for the Light û a simple Cone

Cone cone = new Cone( 1, 1, Primitive.GENERATE_TEXTURE_COORDS, app );

add the geometry to its parent group

g.addChild( cone );

add a behavior to animate the TextureAttributes

attachBehavior( new TextureAnimationBehavior( m_TextureAttributes ) );

return g;

}

}

The TextureAnimationBehavior performs the work of modifying the Transform3D within the LightÆs TextureAttributes object. Every 300 milliseconds the Transform3D is randomly modified to move the texture image around the Y-axis of the Cone.

 

class TextureAnimationBehavior extends Behavior

{

the wake up condition for the behavior

protected WakeupCondition m_WakeupCondition = null;

protected Transform3D m_Transform3D = null;

protected TextureAttributes m_TextureAttributes = null;

public TextureAnimationBehavior( TextureAttributes texAttribs )

{

m_TextureAttributes = texAttribs;

m_Transform3D = new Transform3D();

m_TextureAttributes.setCapability( TextureAttributes.ALLOW_TRANSFORM_WRITE );

create the WakeupCriterion for the behavior

WakeupCriterion criterionArray[] = new WakeupCriterion[1];

criterionArray[0] = new WakeupOnElapsedTime( 300 );

save the WakeupCriterion for the behavior

m_WakeupCondition = new WakeupOr( criterionArray );

}

public void initialize()

{

apply the initial WakeupCriterion

wakeupOn( m_WakeupCondition );

}

public void processStimulus( java.util.Enumeration criteria )

{

while( criteria.hasMoreElements() )

{

WakeupCriterion wakeUp = (WakeupCriterion) criteria.nextElement();

if( wakeUp instanceof WakeupOnElapsedTime )

{

make a small random change to the Transform3D and apply it to the TextureAttributes

m_Transform3D.rotY( Utils.getRandomNumber( 0.4, 0.4 ) );

m_TextureAttributes.setTextureTransform( m_Transform3D );

}

}

assign the next WakeUpCondition, so we are notified again

wakeupOn( m_WakeupCondition );

}

}

Note that the Lights object do not use a shared Appearance object or all the "random" changes to the Lights texture images would be synchronized! When running the example application you will sometimes see that the Water objects and the Light Objects are not rendered in the correct order. This is because both objects are Transparent and Java 3D does not have (full) built in support for determining the rendering order of transparent objects. An application specific fix for the example application would be to force the Water objects (they are always on the floor) to render before the Light objects (which are always off the floor) using an OrderedGroup.

figure 6. A frame rendered by KeyNavigateTest with the small_map.gif world loaded. Note that the middle torch is rendered behind the water on the ground.